// Copyright (c) 2021 百小僧, Baiqian Co.,Ltd.
// Util is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2. 
// You may obtain a copy of Mulan PSL v2 at:
//             https://gitee.com/dotnetchina/Util/blob/master/LICENSE

using System;

namespace Terra.Core.Common.Utils;

/// <summary>
/// 日期时间扩展
/// </summary>
public static class DateTimeExtensions
{
    #region 时间戳

    /// <summary>
    /// 转换为时间戳
    /// </summary>
    /// <param name="dateTime">时间</param>
    /// <param name="milliseconds">是否使用毫秒</param>
    public static long ToTimestamp(this DateTime dateTime, bool milliseconds = true)
    {
        var timestamp = dateTime.ToUniversalTime().Ticks - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks;
        if (milliseconds)
            return timestamp / 10000;
        return timestamp / 10000000;
    }

    /// <summary>
    /// 从时间戳转换
    /// </summary>
    /// <param name="timestamp">时间戳</param>
    /// <param name="milliseconds">是否使用毫秒</param>
    public static DateTime FromTimestamp(this long timestamp, bool milliseconds = true)
    {
        var ticks = milliseconds ? timestamp * 10000 : timestamp * 10000000;
        return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddTicks(ticks).ToLocalTime();
    }

    #endregion

    #region 日期判断

    /// <summary>
    /// 是否为工作日
    /// </summary>
    /// <param name="date">日期</param>
    public static bool IsWeekday(this DateTime date)
    {
        return date.DayOfWeek != DayOfWeek.Saturday && date.DayOfWeek != DayOfWeek.Sunday;
    }

    /// <summary>
    /// 是否为周末
    /// </summary>
    /// <param name="date">日期</param>
    public static bool IsWeekend(this DateTime date)
    {
        return !date.IsWeekday();
    }

    /// <summary>
    /// 是否为今天
    /// </summary>
    /// <param name="date">日期</param>
    public static bool IsToday(this DateTime date)
    {
        return date.Date == DateTime.Today;
    }

    #endregion

    #region 日期计算

    /// <summary>
    /// 获取月初
    /// </summary>
    /// <param name="date">日期</param>
    public static DateTime GetFirstDayOfMonth(this DateTime date)
    {
        return new DateTime(date.Year, date.Month, 1);
    }

    /// <summary>
    /// 获取月末
    /// </summary>
    /// <param name="date">日期</param>
    public static DateTime GetLastDayOfMonth(this DateTime date)
    {
        return date.GetFirstDayOfMonth().AddMonths(1).AddDays(-1);
    }

    /// <summary>
    /// 获取周一
    /// </summary>
    /// <param name="date">日期</param>
    public static DateTime GetMonday(this DateTime date)
    {
        var dayOfWeek = (int)date.DayOfWeek;
        return date.AddDays(dayOfWeek == 0 ? -6 : 1 - dayOfWeek);
    }

    /// <summary>
    /// 获取周日
    /// </summary>
    /// <param name="date">日期</param>
    public static DateTime GetSunday(this DateTime date)
    {
        return date.GetMonday().AddDays(6);
    }

    /// <summary>
    /// 获取季度初
    /// </summary>
    /// <param name="date">日期</param>
    public static DateTime GetFirstDayOfQuarter(this DateTime date)
    {
        var month = date.Month;
        if (month <= 3)
            return new DateTime(date.Year, 1, 1);
        if (month <= 6)
            return new DateTime(date.Year, 4, 1);
        if (month <= 9)
            return new DateTime(date.Year, 7, 1);
        return new DateTime(date.Year, 10, 1);
    }

    /// <summary>
    /// 获取季度末
    /// </summary>
    /// <param name="date">日期</param>
    public static DateTime GetLastDayOfQuarter(this DateTime date)
    {
        return date.GetFirstDayOfQuarter().AddMonths(3).AddDays(-1);
    }

    #endregion

    #region 格式化

    /// <summary>
    /// 友好显示
    /// </summary>
    /// <param name="date">日期</param>
    public static string ToFriendlyDisplay(this DateTime date)
    {
        var span = DateTime.Now - date;
        if (span.TotalMinutes < 1)
            return "刚刚";
        if (span.TotalHours < 1)
            return $"{(int)span.TotalMinutes}分钟前";
        if (span.TotalDays < 1)
            return $"{(int)span.TotalHours}小时前";
        if (span.TotalDays < 30)
            return $"{(int)span.TotalDays}天前";
        if (date.Year == DateTime.Now.Year)
            return date.ToString("MM-dd");
        return date.ToString("yyyy-MM-dd");
    }

    #endregion
}